home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / psi110g.zip / LAPB.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  27KB  |  819 lines

  1. /* Link Access Procedures Balanced (LAPB), the upper sublayer of
  2.  * AX.25 Level 2.
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  *
  5.  * 92/02/07 WG7J
  6.  * Modified to drop ax.25 route records in cases where routes
  7.  * were added by the connections. Inspired by K4TQL
  8.  */
  9. #include "global.h"
  10. #ifdef AX25
  11. #include "mbuf.h"
  12. #include "timer.h"
  13. #include "ax25.h"
  14. #include "lapb.h"
  15. #include "ip.h"
  16. #include "netrom.h"
  17.   
  18. /* This forces data sent by jumpstarting a mailbox connect to
  19.  * resend the header etc. when the first UA reply is missed, and
  20.  * a second SABM is received for the same connection
  21.  * added by Ron Murray VK6ZJM, Murray_RJ@cc.curtin.edu.au
  22.  */
  23. #define SABM_HOLDOFF
  24.   
  25. static void handleit __ARGS((struct ax25_cb *axp,int pid,struct mbuf *bp));
  26. static void procdata __ARGS((struct ax25_cb *axp,struct mbuf *bp));
  27. static int ackours __ARGS((struct ax25_cb *axp,int16 n));
  28. static void clr_ex __ARGS((struct ax25_cb *axp));
  29. static void enq_resp __ARGS((struct ax25_cb *axp));
  30. static void inv_rex __ARGS((struct ax25_cb *axp));
  31. static void drop_axr __ARGS((struct ax25_cb *axp));
  32.   
  33. /*needed for mailbox jumpstart - WG7J */
  34. #ifdef MAILBOX
  35. #ifdef NETROM
  36. extern struct nrnbr_tab *find_nrnbr __ARGS((char *, struct iface *));
  37. #endif
  38. #endif
  39.   
  40. /*If we have an AX.25 AUTO route record, drop it.*/
  41. static void
  42. drop_axr(axp)
  43. struct ax25_cb *axp;
  44. {
  45.     struct ax_route *axr;
  46.   
  47.     axr = ax_lookup(axp->remote,axp->iface);
  48.     if(axr != NULLAXR && axr->type != AX_LOCAL)
  49.         ax_drop(axp->remote,axp->iface);
  50.   
  51. }
  52.   
  53. /* Process incoming frames */
  54. int
  55. lapb_input(axp,cmdrsp,bp)
  56. struct ax25_cb *axp;            /* Link control structure */
  57. int cmdrsp;                     /* Command/response flag */
  58. struct mbuf *bp;                /* Rest of frame, starting with ctl */
  59. {
  60.     int control;
  61.     int class;              /* General class (I/S/U) of frame */
  62.     int16 type;             /* Specific type (I/RR/RNR/etc) of frame */
  63.     char pf;                /* extracted poll/final bit */
  64.     char poll = 0;
  65.     char final = 0;
  66.     int16 nr;               /* ACK number of incoming frame */
  67.     int16 ns;               /* Seq number of incoming frame */
  68.     int16 tmp;
  69. #ifdef MAILBOX
  70. #ifdef NETROM
  71.     int ifnum;      /*used to find possible netrom connect*/
  72. #endif
  73. #endif
  74.   
  75.     if(bp == NULLBUF || axp == NULLAX25){
  76.         free_p(bp);
  77.         return -1;
  78.     }
  79.   
  80.     /* Extract the various parts of the control field for easy use */
  81.     if((control = PULLCHAR(&bp)) == -1){
  82.         free_p(bp);     /* Probably not necessary */
  83.         return -1;
  84.     }
  85.     type = ftype(control);
  86.     class = type & 0x3;
  87.     pf = control & PF;
  88.     /* Check for polls and finals */
  89.     if(pf){
  90.         switch(cmdrsp){
  91.             case LAPB_COMMAND:
  92.                 poll = YES;
  93.                 break;
  94.             case LAPB_RESPONSE:
  95.                 final = YES;
  96.                 break;
  97.         }
  98.     }
  99.     /* Extract sequence numbers, if present */
  100.     switch(class){
  101.         case I:
  102.         case I+2:
  103.             ns = (control >> 1) & MMASK;
  104.         case S: /* Note fall-thru */
  105.             nr = (control >> 5) & MMASK;
  106.             break;
  107.     }
  108.     /* This section follows the SDL diagrams by K3NA fairly closely */
  109.     switch(axp->state){
  110.         case LAPB_DISCONNECTED:
  111.         switch(type){
  112.             case SABM:      /* Initialize or reset link */
  113.         /* This a new incoming connection.
  114.          * Accept if we have enough memory left
  115.          * 920115 - WG7J
  116.          */
  117.                 if(availmem() < Memthresh){
  118.                     sendctl(axp,LAPB_RESPONSE,DM|pf);
  119.                     break;
  120.                 }
  121.                 sendctl(axp,LAPB_RESPONSE,UA|pf);   /* Always accept */
  122.                 clr_ex(axp);
  123.                 axp->unack = axp->vr = axp->vs = 0;
  124.                 lapbstate(axp,LAPB_CONNECTED);/* Resets state counters */
  125.                 axp->srt = axp->iface->ax25->irtt;  /* Set ax.25 irtt per interface - WG7J */
  126.                 axp->mdev = 0;
  127.                 set_timer(&axp->t1,2*axp->srt);
  128.                 start_timer(&axp->t3);
  129.                 start_timer(&axp->t4);
  130. #ifdef SABM_HOLDOFF
  131.                 axp->flags.rxd_I_frame = 0;    /* nothing received yet */
  132. #endif
  133. #ifdef MAILBOX
  134.         /* Jump-start the mailbox. This causes the [NET-H$] prompt to
  135.          * be sent Immediately, instead of after the first data packet
  136.          * Only conenctions to the bbscall, the alias, or the convers
  137.          * call get jumpstarted.
  138.          * 5/17/93 WG7J
  139.          */
  140.                 if(axp->jumpstarted & (ALIAS_LINK+CONF_LINK+TTY_LINK)) {
  141.                     axp->jumpstarted += JUMPSTARTED;
  142.                     s_arcall(axp,0);
  143.                 }
  144. #endif /* MAILBOX */
  145.                 break;
  146.             case DISC:      /* Always answer a DISC with a DM */
  147.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  148.                 break;
  149.             case DM:        /* Ignore to avoid infinite loops */
  150.                 break;
  151.             default:        /* All others get DM */
  152.                 if(poll)
  153.                     sendctl(axp,LAPB_RESPONSE,DM|pf);
  154.                 break;
  155.         }
  156.             if(axp->state == LAPB_DISCONNECTED){    /* we can close connection */
  157.                 stop_timer(&axp->t1);   /* waste all the timers */
  158.                 stop_timer(&axp->t3);
  159.                 stop_timer(&axp->t4);
  160.                 free_q(&axp->txq);      /* lose transmit queue */
  161.                 drop_axr(axp);          /* drop ax25 route */
  162.                 del_ax25(axp);      /* clean out the trash */
  163.                 free_p(bp);
  164.                 return 0;
  165.             }
  166.             break;
  167.         case LAPB_SETUP:
  168.         switch(type){
  169.             case SABM:      /* Simultaneous open */
  170.                 sendctl(axp,LAPB_RESPONSE,UA|pf);
  171.                 break;
  172.             case DISC:
  173.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  174. #ifdef NETROM
  175.                 nr_derate(axp);
  176. #endif
  177.                 drop_axr(axp);      /* drop ax25 route */
  178.                 free_q(&axp->txq);
  179.                 stop_timer(&axp->t1);
  180.                 axp->reason = LB_DM;
  181.                 lapbstate(axp,LAPB_DISCONNECTED);
  182.                 free_p(bp);
  183.                 return 0;
  184. /*            break;    */
  185.             case UA:        /* Connection accepted */
  186.             /* Note: xmit queue not cleared */
  187.                 stop_timer(&axp->t1);
  188.                 start_timer(&axp->t3);
  189.                 axp->unack = axp->vr = axp->vs = 0;
  190.                 lapbstate(axp,LAPB_CONNECTED);
  191.                 start_timer(&axp->t4);
  192.                 break;
  193.             case DM:        /* Connection refused */
  194.                 free_q(&axp->txq);
  195.                 stop_timer(&axp->t1);
  196.                 axp->reason = LB_DM;
  197.                 lapbstate(axp,LAPB_DISCONNECTED);
  198.                 free_p(bp);
  199.                 return 0;
  200. /*            break;    */
  201.             default:        /* Respond with DM only to command polls */
  202.                 if(poll)
  203.                     sendctl(axp,LAPB_RESPONSE,DM|pf);
  204.                 break;
  205.         }
  206.             break;
  207.         case LAPB_DISCPENDING:
  208.         switch(type){
  209.             case SABM:
  210.                 sendctl(axp,LAPB_RESPONSE,DM|pf);
  211.                 drop_axr(axp);          /* drop ax25 route */
  212.                 break;
  213.             case DISC:
  214.                 sendctl(axp,LAPB_RESPONSE,UA|pf);
  215.                 drop_axr(axp);          /* drop ax25 route */
  216.                 break;
  217.             case UA:
  218.             case DM:
  219.                 stop_timer(&axp->t1);
  220.                 lapbstate(axp,LAPB_DISCONNECTED);
  221.                 free_p(bp);
  222.                 return 0;
  223. /*             break; */
  224.             default:        /* Respond with DM only to command polls */
  225.                 if(poll)
  226.                     sendctl(axp,LAPB_RESPONSE,DM|pf);
  227.                 drop_axr(axp);          /* drop ax25 route */
  228.                 break;
  229.         }
  230.             break;
  231.         case LAPB_CONNECTED:
  232.         switch(type){
  233.             case SABM:
  234.                 sendctl(axp,LAPB_RESPONSE,UA|pf);
  235. #ifdef SABM_HOLDOFF
  236.                 if (axp->flags.rxd_I_frame) {
  237.         /* only reset if we've had a */
  238.         /* valid I-frame. Otherwise he */
  239.         /* may just not have got our UA */
  240. #endif
  241.                     clr_ex(axp);
  242.                     free_q(&axp->txq);
  243.                     stop_timer(&axp->t1);
  244.                     start_timer(&axp->t3);
  245.                     axp->unack = axp->vr = axp->vs = 0;
  246.                     lapbstate(axp,LAPB_CONNECTED); /* Purge queues */
  247. #ifdef SABM_HOLDOFF
  248.                 }
  249. #endif
  250.                 break;
  251.             case DISC:
  252.                 free_q(&axp->txq);
  253.                 sendctl(axp,LAPB_RESPONSE,UA|pf);
  254.                 stop_timer(&axp->t1);
  255.                 stop_timer(&axp->t3);
  256.                 axp->reason = LB_NORMAL;
  257.                 lapbstate(axp,LAPB_DISCONNECTED);
  258.                 free_p(bp);
  259.                 return 0;
  260. /*            break;    */
  261.             case DM:
  262.                 axp->reason = LB_DM;
  263.                 lapbstate(axp,LAPB_DISCONNECTED);
  264.                 free_p(bp);
  265.                 return 0;
  266. /*            break;    */
  267.             case UA:
  268.                 est_link(axp);
  269.                 lapbstate(axp,LAPB_SETUP);      /* Re-establish */
  270.                 break;
  271.             case FRMR:
  272.                 est_link(axp);
  273.                 lapbstate(axp,LAPB_SETUP);      /* Re-establish link */
  274.                 break;
  275.             case RR:
  276.             case RNR:
  277.                 axp->flags.remotebusy = (type == RNR) ? YES : NO;
  278.                 if(poll)
  279.                     enq_resp(axp);
  280.                 ackours(axp,nr);
  281.                 break;
  282.             case REJ:
  283.                 axp->flags.remotebusy = NO;
  284.                 if(poll)
  285.                     enq_resp(axp);
  286.                 ackours(axp,nr);
  287.                 stop_timer(&axp->t1);
  288.                 start_timer(&axp->t3);
  289.             /* This may or may not actually invoke transmission,
  290.              * depending on whether this REJ was caused by
  291.              * our losing his prior ACK.
  292.              */
  293.                 inv_rex(axp);
  294.                 break;
  295.             case I:
  296.                 ackours(axp,nr); /** == -1) */
  297. #ifdef SABM_HOLDOFF
  298.                 axp->flags.rxd_I_frame = 1;   /* we got something */
  299. #endif
  300.                 start_timer(&axp->t4);
  301.                 if(len_p(axp->rxq) >= axp->window){
  302.                 /* Too bad he didn't listen to us; he'll
  303.                  * have to resend the frame later. This
  304.                  * drastic action is necessary to avoid
  305.                  * deadlock.
  306.                  */
  307.                     if(poll)
  308.                         sendctl(axp,LAPB_RESPONSE,RNR|pf);
  309.                     free_p(bp);
  310.                     bp = NULLBUF;
  311.                     break;
  312.                 }
  313.             /* Reject or ignore I-frames with receive sequence number errors */
  314.                 if(ns != axp->vr){
  315.                     if(axp->proto == V1 || !axp->flags.rejsent){
  316.                         axp->flags.rejsent = YES;
  317.                         sendctl(axp,LAPB_RESPONSE,REJ | pf);
  318.                     } else if(poll)
  319.                         enq_resp(axp);
  320.                     axp->response = 0;
  321.                     break;
  322.                 }
  323.                 axp->flags.rejsent = NO;
  324.                 axp->vr = (axp->vr+1) & MMASK;
  325.                 tmp = len_p(axp->rxq) >= axp->window ? RNR : RR;
  326.                 if(poll){
  327.                     sendctl(axp,LAPB_RESPONSE,tmp|PF);
  328.                 } else {
  329.                     axp->response = tmp;
  330.                 }
  331.                 procdata(axp,bp);
  332.                 bp = NULLBUF;
  333.                 break;
  334.             default:        /* All others ignored */
  335.                 break;
  336.         }
  337.             break;
  338.         case LAPB_RECOVERY:
  339.         switch(type){
  340.             case SABM:
  341.                 sendctl(axp,LAPB_RESPONSE,UA|pf);
  342. #ifdef SABM_HOLDOFF
  343.                 if (axp->flags.rxd_I_frame) {
  344.         /* only reset if we've had a */
  345.         /* valid I-frame. Otherwise he */
  346.         /* may just not have got our UA */
  347. #endif
  348.                     clr_ex(axp);
  349.                     stop_timer(&axp->t1);
  350.                     start_timer(&axp->t3);
  351.                     axp->unack = axp->vr = axp->vs = 0;
  352.                     lapbstate(axp,LAPB_CONNECTED); /* Purge queues */
  353.                     if(!run_timer(&axp->t4))
  354.                         start_timer(&axp->t4);
  355. #ifdef SABM_HOLDOFF
  356.                 }
  357. #endif
  358.                 break;
  359.             case DISC:
  360.                 free_q(&axp->txq);
  361.                 sendctl(axp,LAPB_RESPONSE,UA|pf);
  362.                 stop_timer(&axp->t1);
  363.                 stop_timer(&axp->t3);
  364.                 axp->response = UA;
  365.                 axp->reason = LB_NORMAL;
  366.                 lapbstate(axp,LAPB_DISCONNECTED);
  367.                 free_p(bp);
  368.                 return 0;
  369. /*            break;    */
  370.             case DM:
  371. #ifdef NETROM
  372.                 nr_derate(axp);
  373. #endif
  374.                 axp->reason = LB_DM;
  375.                 lapbstate(axp,LAPB_DISCONNECTED);
  376.                 free_p(bp);
  377.                 return 0;
  378. /*            break;    */
  379.             case UA:
  380.                 est_link(axp);
  381.                 lapbstate(axp,LAPB_SETUP);      /* Re-establish */
  382.                 break;
  383.             case FRMR:
  384.                 est_link(axp);
  385.                 lapbstate(axp,LAPB_SETUP);      /* Re-establish link */
  386.                 break;
  387.             case RR:
  388.             case RNR:
  389.                 axp->flags.remotebusy = (type == RNR) ? YES : NO;
  390.                 if(axp->proto == V1 || final){
  391.                     stop_timer(&axp->t1);
  392.                     ackours(axp,nr);
  393.                     if(axp->unack != 0){
  394.                         inv_rex(axp);
  395.                     } else {
  396.                         start_timer(&axp->t3);
  397.                         lapbstate(axp,LAPB_CONNECTED);
  398.                         if(!run_timer(&axp->t4))
  399.                             start_timer(&axp->t4);
  400.                     }
  401.                 } else {
  402.                     if(poll)
  403.                         enq_resp(axp);
  404.                     ackours(axp,nr);
  405.                 /* Keep timer running even if all frames
  406.                  * were acked, since we must see a Final
  407.                  */
  408.                     if(!run_timer(&axp->t1))
  409.                         start_timer(&axp->t1);
  410.                 }
  411.                 break;
  412.             case REJ:
  413.                 axp->flags.remotebusy = NO;
  414.             /* Don't insist on a Final response from the old proto */
  415.                 if(axp->proto == V1 || final){
  416.                     stop_timer(&axp->t1);
  417.                     ackours(axp,nr);
  418.                     if(axp->unack != 0){
  419.                         inv_rex(axp);
  420.                     } else {
  421.                         start_timer(&axp->t3);
  422.                         lapbstate(axp,LAPB_CONNECTED);
  423.                         if(!run_timer(&axp->t4))
  424.                             start_timer(&axp->t4);
  425.                     }
  426.                 } else {
  427.                     if(poll)
  428.                         enq_resp(axp);
  429.                     ackours(axp,nr);
  430.                     if(axp->unack != 0){
  431.                     /* This is certain to trigger output */
  432.                         inv_rex(axp);
  433.                     }
  434.                 /* A REJ that acks everything but doesn't
  435.                  * have the F bit set can cause a deadlock.
  436.                  * So make sure the timer is running.
  437.                  */
  438.                     if(!run_timer(&axp->t1))
  439.                         start_timer(&axp->t1);
  440.                 }
  441.                 break;
  442.             case I:
  443.                 ackours(axp,nr); /** == -1) */
  444. #ifdef SABM_HOLDOFF
  445.                 axp->flags.rxd_I_frame = YES;   /* we got something */
  446. #endif
  447.         /* Make sure timer is running, since an I frame
  448.              * cannot satisfy a poll
  449.              */
  450.                 if(!run_timer(&axp->t1))
  451.                     start_timer(&axp->t1);
  452.                 if(len_p(axp->rxq) >= axp->window){
  453.                 /* Too bad he didn't listen to us; he'll
  454.                  * have to resend the frame later. This
  455.                  * drastic action is necessary to avoid
  456.                  * memory deadlock.
  457.                  */
  458.                     sendctl(axp,LAPB_RESPONSE,RNR | pf);
  459.                     free_p(bp);
  460.                     bp = NULLBUF;
  461.                     break;
  462.                 }
  463.             /* Reject or ignore I-frames with receive sequence number errors */
  464.                 if(ns != axp->vr){
  465.                     if(axp->proto == V1 || !axp->flags.rejsent){
  466.                         axp->flags.rejsent = YES;
  467.                         sendctl(axp,LAPB_RESPONSE,REJ | pf);
  468.                     } else if(poll)
  469.                         enq_resp(axp);
  470.   
  471.                     axp->response = 0;
  472.                     break;
  473.                 }
  474.                 axp->flags.rejsent = NO;
  475.                 axp->vr = (axp->vr+1) & MMASK;
  476.                 tmp = len_p(axp->rxq) >= axp->window ? RNR : RR;
  477.                 if(poll){
  478.                     sendctl(axp,LAPB_RESPONSE,tmp|PF);
  479.                 } else {
  480.                     axp->response = tmp;
  481.                 }
  482.                 procdata(axp,bp);
  483.                 bp = NULLBUF;
  484.                 break;
  485.             default:
  486.                 break;          /* Ignored */
  487.         }
  488.             break;
  489.     }
  490.     free_p(bp);     /* In case anything's left */
  491.   
  492.     /* See if we can send some data, perhaps piggybacking an ack.
  493.      * If successful, lapb_output will clear axp->response.
  494.      */
  495.     lapb_output(axp);
  496.     if(axp->response != 0){
  497.         sendctl(axp,LAPB_RESPONSE,axp->response);
  498.         axp->response = 0;
  499.     }
  500.     return 0;
  501. }
  502.   
  503. /* Handle incoming acknowledgements for frames we've sent.
  504.  * Free frames being acknowledged.
  505.  * Return -1 to cause a frame reject if number is bad, 0 otherwise
  506.  */
  507. static int
  508. ackours(axp,n)
  509. struct ax25_cb *axp;
  510. int16 n;
  511. {
  512.     struct mbuf *bp;
  513.     int acked = 0;  /* Count of frames acked by this ACK */
  514.     int16 oldest;   /* Seq number of oldest unacked I-frame */
  515.     int32 rtt,abserr;
  516.   
  517.     /* Free up acknowledged frames by purging frames from the I-frame
  518.      * transmit queue. Start at the remote end's last reported V(r)
  519.      * and keep going until we reach the new sequence number.
  520.      * If we try to free a null pointer,
  521.      * then we have a frame reject condition.
  522.      */
  523.     oldest = (axp->vs - axp->unack) & MMASK;
  524.     while(axp->unack != 0 && oldest != n){
  525.         if((bp = dequeue(&axp->txq)) == NULLBUF){
  526.             /* Acking unsent frame */
  527.             return -1;
  528.         }
  529.         free_p(bp);
  530.         axp->unack--;
  531.         acked++;
  532.         if(axp->flags.rtt_run && axp->rtt_seq == oldest){
  533.             /* A frame being timed has been acked */
  534.             axp->flags.rtt_run = 0;
  535.             /* Update only if frame wasn't retransmitted */
  536.             if(!axp->flags.retrans){
  537.                 rtt = msclock() - axp->rtt_time;
  538.                 abserr = (rtt > axp->srt) ? rtt - axp->srt :
  539.                 axp->srt - rtt;
  540.   
  541.                 /* Run SRT and mdev integrators */
  542.                 axp->srt = ((axp->srt * 7) + rtt + 4) >> 3;
  543.                 axp->mdev = ((axp->mdev*3) + abserr + 2) >> 2;
  544.                 /* Update timeout */
  545.                 set_timer(&axp->t1,4*axp->mdev+axp->srt);
  546.             }
  547.         }
  548.         axp->flags.retrans = 0;
  549.         axp->retries = 0;
  550.         oldest = (oldest + 1) & MMASK;
  551.     }
  552.     if(axp->unack == 0){
  553.         /* All frames acked, stop timeout */
  554.         stop_timer(&axp->t1);
  555.         start_timer(&axp->t3);
  556.     } else if(acked != 0) {
  557.         /* Partial ACK; restart timer */
  558.         start_timer(&axp->t1);
  559.     }
  560.     if(acked != 0){
  561.         /* If user has set a transmit upcall, indicate how many frames
  562.          * may be queued
  563.          */
  564.         if(axp->t_upcall != NULLVFP)
  565.             (*axp->t_upcall)(axp,axp->paclen * (axp->maxframe - axp->unack));
  566.     }
  567.     return 0;
  568. }
  569.   
  570. /* Establish data link */
  571. void
  572. est_link(axp)
  573. struct ax25_cb *axp;
  574. {
  575.     clr_ex(axp);
  576.     axp->retries = 0;
  577.     sendctl(axp,LAPB_COMMAND,SABM|PF);
  578.     stop_timer(&axp->t3);
  579.     start_timer(&axp->t1);
  580. }
  581. /* Clear exception conditions */
  582. static void
  583. clr_ex(axp)
  584. struct ax25_cb *axp;
  585. {
  586.     axp->flags.remotebusy = NO;
  587.     axp->flags.rejsent = NO;
  588.     axp->response = 0;
  589.     stop_timer(&axp->t3);
  590. }
  591. /* Enquiry response */
  592. static void
  593. enq_resp(axp)
  594. struct ax25_cb *axp;
  595. {
  596.     char ctl;
  597.   
  598.     ctl = len_p(axp->rxq) >= axp->window ? RNR|PF : RR|PF;
  599.     sendctl(axp,LAPB_RESPONSE,ctl);
  600.     axp->response = 0;
  601.     stop_timer(&axp->t3);
  602. }
  603. /* Invoke retransmission */
  604. static void
  605. inv_rex(axp)
  606. struct ax25_cb *axp;
  607. {
  608.     axp->vs -= axp->unack;
  609.     axp->vs &= MMASK;
  610.     axp->unack = 0;
  611. }
  612. /* Send S or U frame to currently connected station */
  613. int
  614. sendctl(axp,cmdrsp,cmd)
  615. struct ax25_cb *axp;
  616. int cmdrsp;
  617. int cmd;
  618. {
  619.     if((ftype((char)cmd) & 0x3) == S)       /* Insert V(R) if S frame */
  620.         cmd |= (axp->vr << 5);
  621.     return sendframe(axp,cmdrsp,cmd,NULLBUF);
  622. }
  623. /* Start data transmission on link, if possible
  624.  * Return number of frames sent
  625.  */
  626. int
  627. lapb_output(axp)
  628. register struct ax25_cb *axp;
  629. {
  630.     register struct mbuf *bp;
  631.     struct mbuf *tbp;
  632.     char control;
  633.     int sent = 0;
  634.     int i;
  635.   
  636.     if(axp == NULLAX25
  637.         || (axp->state != LAPB_RECOVERY && axp->state != LAPB_CONNECTED)
  638.         || axp->flags.remotebusy)
  639.         return 0;
  640.   
  641.     /* Dig into the send queue for the first unsent frame */
  642.     bp = axp->txq;
  643.     for(i = 0; i < axp->unack; i++){
  644.         if(bp == NULLBUF)
  645.             break;  /* Nothing to do */
  646.         bp = bp->anext;
  647.     }
  648.     /* Start at first unsent I-frame, stop when either the
  649.      * number of unacknowledged frames reaches the maxframe limit,
  650.      * or when there are no more frames to send
  651.      */
  652.     while(bp != NULLBUF && axp->unack < axp->maxframe){
  653.         control = I | (axp->vs++ << 1) | (axp->vr << 5);
  654.         axp->vs &= MMASK;
  655.         dup_p(&tbp,bp,0,len_p(bp));
  656.         if(tbp == NULLBUF)
  657.             return sent;    /* Probably out of memory */
  658.         sendframe(axp,LAPB_COMMAND,control,tbp);
  659.         start_timer(&axp->t4);
  660.         axp->unack++;
  661.         /* We're implicitly acking any data he's sent, so stop any
  662.          * delayed ack
  663.          */
  664.         axp->response = 0;
  665.         if(!run_timer(&axp->t1)){
  666.             stop_timer(&axp->t3);
  667.             start_timer(&axp->t1);
  668.         }
  669.         sent++;
  670.         bp = bp->anext;
  671.         if(!axp->flags.rtt_run){
  672.             /* Start round trip timer */
  673.             axp->rtt_seq = (control >> 1) & MMASK;
  674.             axp->rtt_time = msclock();
  675.             axp->flags.rtt_run = 1;
  676.         }
  677.     }
  678.     return sent;
  679. }
  680. /* Set new link state */
  681. void
  682. lapbstate(axp,s)
  683. struct ax25_cb *axp;
  684. int s;
  685. {
  686.     int oldstate;
  687.   
  688.     oldstate = axp->state;
  689.     axp->state = s;
  690.     if(s == LAPB_DISCONNECTED){
  691.         stop_timer(&axp->t1);
  692.         stop_timer(&axp->t3);
  693.         stop_timer(&axp->t4);
  694.         free_q(&axp->txq);
  695.         drop_axr(axp);          /* any ax25 route that hasn't been dropped yet*/
  696.     }
  697.     /* Don't bother the client unless the state is really changing */
  698.     if((oldstate != s) && (axp->s_upcall != NULLVFP))
  699.         (*axp->s_upcall)(axp,oldstate,s);
  700. }
  701. /* Process a valid incoming I frame */
  702. static void
  703. procdata(axp,bp)
  704. struct ax25_cb *axp;
  705. struct mbuf *bp;
  706. {
  707.     int pid;
  708.     int seq;
  709.   
  710.     /* Extract level 3 PID */
  711.     if((pid = PULLCHAR(&bp)) == -1)
  712.         return; /* No PID */
  713.   
  714.     if(axp->segremain != 0){
  715.         /* Reassembly in progress; continue */
  716.         seq = PULLCHAR(&bp);
  717.         if(pid == PID_SEGMENT
  718.         && (seq & SEG_REM) == axp->segremain - 1){
  719.             /* Correct, in-order segment */
  720.             append(&axp->rxasm,bp);
  721.             if((axp->segremain = (seq & SEG_REM)) == 0){
  722.                 /* Done; kick it upstairs */
  723.                 bp = axp->rxasm;
  724.                 axp->rxasm = NULLBUF;
  725.                 pid = PULLCHAR(&bp);
  726.                 handleit(axp,pid,bp);
  727.             }
  728.         } else {
  729.             /* Error! */
  730.             free_p(axp->rxasm);
  731.             axp->rxasm = NULLBUF;
  732.             axp->segremain = 0;
  733.             free_p(bp);
  734.         }
  735.     } else {
  736.         /* No reassembly in progress */
  737.         if(pid == PID_SEGMENT){
  738.             /* Start reassembly */
  739.             seq = PULLCHAR(&bp);
  740.             if(!(seq & SEG_FIRST)){
  741.                 free_p(bp);     /* not first seg - error! */
  742.             } else {
  743.                 /* Put first segment on list */
  744.                 axp->segremain = seq & SEG_REM;
  745.                 axp->rxasm = bp;
  746.             }
  747.         } else {
  748.             /* Normal frame; send upstairs */
  749.             handleit(axp,pid,bp);
  750.         }
  751.     }
  752. }
  753. /* New-style frame segmenter. Returns queue of segmented fragments, or
  754.  * original packet if small enough
  755.  */
  756. struct mbuf *
  757. segmenter(bp,ssize)
  758. struct mbuf *bp;        /* Complete packet */
  759. int16 ssize;            /* Max size of frame segments */
  760. {
  761.     struct mbuf *result = NULLBUF;
  762.     struct mbuf *bptmp,*bp1;
  763.     int16 len,offset;
  764.     int segments;
  765.   
  766.     /* See if packet is too small to segment. Note 1-byte grace factor
  767.      * so the PID will not cause segmentation of a 256-byte IP datagram.
  768.      */
  769.     len = len_p(bp);
  770.     if(len <= ssize+1)
  771.         return bp;      /* Too small to segment */
  772.   
  773.     ssize -= 2;             /* ssize now equal to data portion size */
  774.     segments = 1 + (len - 1) / ssize;       /* # segments  */
  775.     offset = 0;
  776.   
  777.     while(segments != 0){
  778.         offset += dup_p(&bptmp,bp,offset,ssize);
  779.         if(bptmp == NULLBUF){
  780.             free_q(&result);
  781.             break;
  782.         }
  783.         /* Make room for segmentation header */
  784.         if((bp1 = pushdown(bptmp,2)) == NULLBUF){
  785.             free_p(bptmp);
  786.             free_q(&result);
  787.             break;
  788.         }
  789.         bp1->data[0] = PID_SEGMENT;
  790.         bp1->data[1] = --segments;
  791.         if(offset == ssize)
  792.             bp1->data[1] |= SEG_FIRST;
  793.         enqueue(&result,bp1);
  794.     }
  795.     free_p(bp);
  796.     return result;
  797. }
  798.   
  799. static void
  800. handleit(axp,pid,bp)
  801. struct ax25_cb *axp;
  802. int pid;
  803. struct mbuf *bp;
  804. {
  805.     struct axlink *ipp;
  806.   
  807.     for(ipp = Axlink;ipp->funct != NULL;ipp++){
  808.         if(ipp->pid == pid)
  809.             break;
  810.     }
  811.     if(ipp->funct != NULL)
  812.         (*ipp->funct)(axp->iface,axp,NULLCHAR,NULLCHAR,bp,0);
  813.     else
  814.         free_p(bp);
  815. }
  816.   
  817. #endif /* AX25 */
  818.   
  819.